package com.xbongbong.pro.service.toolbox.statistic.util;

import com.xbongbong.paas.toolbox.util.Arith;
import com.xbongbong.paas.toolbox.util.DateUtil;
import com.xbongbong.paas.toolbox.util.StringUtil;
import com.xbongbong.pro.constant.I18nStringConstant;
import com.xbongbong.pro.enums.AccessLinkEnum;
import com.xbongbong.pro.enums.TimeTypeEnum;
import com.xbongbong.pro.statistic.constant.FundStatisticsConstant;
import com.xbongbong.pro.statistic.enums.IndicatorRuleEnum;
import com.xbongbong.pro.statistic.enums.MoneyUnitEnum;
import com.xbongbong.pro.statistic.enums.NumFormatEnum;
import com.xbongbong.pro.statistic.enums.SystemCodeEnum;
import com.xbongbong.pro.statistic.enums.ValueTypeEnum;
import com.xbongbong.pro.statistic.result.pojo.AggsBucketsPojo;
import com.xbongbong.pro.statistic.result.pojo.ChartPkParamPojo;
import com.xbongbong.pro.statistic.result.pojo.ChartResultPojo;
import com.xbongbong.pro.statistic.result.pojo.ElasticAggsPojo;
import com.xbongbong.pro.statistic.result.pojo.MomYoyTimeListPojo;
import com.xbongbong.pro.statistic.result.pojo.TimeListPojo;
import com.xbongbong.pro.statistic.result.pojo.vo.ChartResultValueDetailVO;
import com.xbongbong.saas.constant.BasicConstant;
import com.xbongbong.saas.constant.PageConstant;
import org.apache.commons.lang.BooleanUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.i18n.LocaleContextHolder;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.Objects;

/**
 * 图表结果工具类
 * @author zcp
 * @version v1.0
 * @date 2019/4/5 15:14
 * @since v1.0
 */
public class ChartResultUtil {
    private static final Logger LOG = LoggerFactory.getLogger(ChartResultUtil.class);

    /**
     * 计算比率，有以下几个规则：
     * （1）分子or分母为0，直接返回0
     * （2）返回结果计算公式为：count/total * 100，即会对count/total的结果乘以100，以方便页面直接拼“%”
     * （3）最终结果，如果大于0，则会保留两位小数
     * @param count 分子
     * @param total 分母
     * @return java.lang.Double 返回count/total * 100
     * @author zcp
     * @date 2019/2/23 20:43
     * @since v1.0
     * @version v1.0
     */
    public static Double getRate(Integer count, Integer total) {
        if (count == null || count == 0 || total == null || total == 0) {
            return 0D;
        }
        // 乘以100，前端显示直接拼“%”即可
        Double rate = Arith.div(count, total) * 100;
        if (rate > 0) {
            rate = StringUtil.toDouble(StringUtil.formatDouble(rate, 2, 1));
        }
        return rate;
    }
    /**
     * 处理计算日均时的timeType问题，比如：
     * 当筛选年的时候，下面的图形是转换为12个月（桶）的，那每个桶日均天数应该按照一个月的22天，而不是筛选年就按照22*12天
     * @param timeType 筛选的时间类型
     * @return 计算日均数应该按照哪个类型
     * @author zcp
     * @since v1.0
     * @version v1.0
     * @date 2017-11-22 下午3:32:07
     */
    public static Integer getAverageTimeType(Integer timeType) {
        Integer perTimeType = timeType;
        if (timeType.equals(TimeTypeEnum.YEAR.getCode())
                || timeType.equals(TimeTypeEnum.YEAR_HALF_UP.getCode())
                || timeType.equals(TimeTypeEnum.YEAR_HALF_DOWN.getCode())
                || timeType.equals(TimeTypeEnum.SEASON.getCode())) {
            //筛选年、半年、季度时，图形内展示的是月，因此计算日均的时候要按照月
            perTimeType = TimeTypeEnum.MONTH.getCode();
        } else if (timeType.equals(TimeTypeEnum.MONTH.getCode())
                || timeType.equals(TimeTypeEnum.MONTH_LAST.getCode())
                || timeType.equals(TimeTypeEnum.WEEK.getCode())
                || timeType.equals(TimeTypeEnum.WEEK_LAST.getCode())) {
            //筛选月、周时，图形内展示的是日，因此计算日均的时候要按照日
            perTimeType = TimeTypeEnum.DAY.getCode();
        }
        return perTimeType;
    }
    /**
     * 只有计算日均时用到
     *
     * @param timeType 对应枚举TimeTypeEnum
     * @param count 计算平均值时的被除数
     * @param scale 小数点后位数
     * @param betweenDays 自定义时间段之间的天数
     * @return double
     * @author 徐俊杰
     * @date 2019/2/24 17:14
     * @since v1.0
     */
    public static double getAverageDay(Integer timeType, Double count, int scale, int betweenDays) {
        //默认是一天
        Integer averageDayCount = 1;
        if (timeType.equals(TimeTypeEnum.YEAR.getCode())) {
            //按照年算日均
            averageDayCount = BasicConstant.AVERAGE_YEAR;
        }else if (timeType.equals(TimeTypeEnum.YEAR_HALF_UP.getCode()) || timeType.equals(TimeTypeEnum.YEAR_HALF_DOWN.getCode())) {
            //半年
            averageDayCount = BasicConstant.AVERAGE_SEASON * 2;
        }else if (timeType.equals(TimeTypeEnum.SEASON.getCode())) {
            averageDayCount = BasicConstant.AVERAGE_SEASON;
        }else if (timeType.equals(TimeTypeEnum.MONTH.getCode()) || timeType.equals(TimeTypeEnum.MONTH_LAST.getCode())) {
            averageDayCount = BasicConstant.AVERAGE_MONTH;
        }else if (timeType.equals(TimeTypeEnum.WEEK.getCode()) || timeType.equals(TimeTypeEnum.WEEK_LAST.getCode())) {
            averageDayCount = BasicConstant.AVERAGE_WEEK;
        }else if (timeType.equals(TimeTypeEnum.DAY.getCode()) || timeType.equals(TimeTypeEnum.DAY_LAST.getCode())) {
            //今日、昨日
            averageDayCount = 1;
        }else if (timeType.equals(TimeTypeEnum.CUSTOM.getCode())) {
            //自定义类型获取自定义天数
            averageDayCount = betweenDays;
        }
        return Arith.div(count, averageDayCount, scale);
    }
    /**
     * 获取环比、同比的比例
     *
     * @param now 当前时间
     * @param last 环比、同比
     * @return java.lang.Double
     * @author 徐俊杰
     * @date 2019/2/28 8:47
     * @since v1.0
     */
    public static Double getMomYoyRate(Double now, Double last) {
        double minusValue = now - last;
        Double compareRate = 0D;
        if (minusValue != 0) {
            //如果为0则代表未变动，否则说明增长或减少了
            compareRate = StringUtil.getRate(minusValue, last, 100);
        }
        return compareRate;
    }

    /**
     * 格式化page和pageSize，防止为空情况
     * @param chartResultPojo 参数pojo
     * @param defaultPageSize 默认每页数量
     * @author zcp
     * @date 2019/4/10 10:50
     * @since v1.0
     * @version v1.0
     */
    public static void formatPage(ChartResultPojo chartResultPojo, int defaultPageSize){
        Integer page = chartResultPojo.getPage();
        Integer pageSize = chartResultPojo.getPageSize();
        if (page == null){
            chartResultPojo.setPage(PageConstant.DEFAULT_INDEX_PAGE);
        }
        if (pageSize == null){
            chartResultPojo.setPageSize(defaultPageSize);
        }
    }

    /**
     * 整体的聚合减去部分的聚合
     *
     * @param overallAggs 整体的聚合结果
     * @param partAggs    部分的聚合结果
     * @return com.xbongbong.pro.statistic.result.pojo.ElasticAggsPojo
     * @author 徐俊杰
     * @date 2019/4/15 11:12
     * @since v1.0
     */
    public static ElasticAggsPojo removePartAggs(ElasticAggsPojo overallAggs, ElasticAggsPojo partAggs) {
        //结果
        ElasticAggsPojo resultAggs = new ElasticAggsPojo();
        //处理总量
        Integer overallTotal = StringUtil.toInt(overallAggs.getTotal(), 0);
        Integer partTotal = StringUtil.toInt(partAggs.getTotal(), 0);
        String resultTotal = String.valueOf(overallTotal - partTotal);
        resultAggs.setTotal(resultTotal);
        //处理分组中的各个值
        List<AggsBucketsPojo> resultBuckets = new ArrayList<>();
        List<AggsBucketsPojo> overallBuckets = overallAggs.getBuckets();
        List<AggsBucketsPojo> partBuckets = partAggs.getBuckets();
        for (int i = 0; i < overallBuckets.size(); i++) {
            //未经排除的值
            AggsBucketsPojo allFinishDelayBucket = overallBuckets.get(i);
            Integer allFinishDelayValue = StringUtil.toInt(allFinishDelayBucket.getValue());
            //需要排除的值
            AggsBucketsPojo notStatisticalBucket = partBuckets.get(i);
            Integer notStatisticalValue = StringUtil.toInt(notStatisticalBucket.getValue());
            //结果值
            String statisticalValue = String.valueOf(allFinishDelayValue - notStatisticalValue);
            AggsBucketsPojo statisticalBucket = new AggsBucketsPojo(allFinishDelayBucket.getKey(), statisticalValue);
            resultBuckets.add(statisticalBucket);
        }
        resultAggs.setBuckets(resultBuckets);
        return resultAggs;
    }

    /**
     * 总量相关结果处理
     *
     * @param timePeriodAggs 时间段分组的聚合结果
     * @param pastTotal 开始时间之前的总量
     * @param valueTypeEnum 值的类型
     * @param chartResultPojo startTime
     * @param futureCalc 未来时间是否计算（如客户总数折线图，超过当前时间的，都用“--”标识，不再计算数量） 0否 1是，默认1计算
     * @return com.xbongbong.pro.statistic.result.pojo.ElasticAggsPojo
     * @author 徐俊杰
     * @date 2019/4/16 9:13
     * @since v1.0
     */
    public static ElasticAggsPojo totalAggs(ElasticAggsPojo timePeriodAggs, Integer pastTotal, ValueTypeEnum valueTypeEnum, ChartResultPojo chartResultPojo, int futureCalc) {
        //处理总数
        Integer total = StringUtil.toInt(timePeriodAggs.getTotal(), 0);
        total += pastTotal;
        timePeriodAggs.setTotal(String.valueOf(total));
        if (valueTypeEnum == ValueTypeEnum.ARRAY_TYPE) {
            //把桶内每个值都拼上startTime时间点之前的
            List<AggsBucketsPojo> aggsBucketsPojoList = new ArrayList<>();
            Integer now = DateUtil.getInt();
            //不计算未来时间---startTimeList的大小和buckets对应
            List<Integer> startTimeList = chartResultPojo.getStartTimeList();
            List<AggsBucketsPojo> buckets = timePeriodAggs.getBuckets();
            for (int j = 0; j < buckets.size(); j++) {
                AggsBucketsPojo aggsBucketsPojo = buckets.get(j);
                String countStr = aggsBucketsPojo.getValue();
                Integer count = StringUtil.toInt(countStr, 0);
                pastTotal += count;
                String value = String.valueOf(pastTotal);
                if (futureCalc == 0) {
                    Integer time = startTimeList.get(j);
                    if (time > now) {
                        value = "-";
                    }
                }
                AggsBucketsPojo bucketsPojo = new AggsBucketsPojo(aggsBucketsPojo.getKey(), value);
                aggsBucketsPojoList.add(bucketsPojo);
            }
            //把处理过后的置入
            timePeriodAggs.setBuckets(aggsBucketsPojoList);
        }
        return timePeriodAggs;
    }

    /**
     * 获取同比或者环比的时间
     *
     * @param chartResultPojoCopy 装开始结束时间的实体
     * @param momFlag 同比还是环比
     * @param startTime 开始时间
     * @param endTime 结束时间
     * @author 徐俊杰
     * @date 2019/4/19 11:29
     * @since v1.0
     */
    public static void momOrYoyTime(ChartResultPojo chartResultPojoCopy, boolean momFlag, Integer startTime, Integer endTime) {
        int lastStartTime;
        int lastEndTime;
        if (momFlag) {
            //环比，上月开始--截止，startTime的前一个月，作为环比的开始时间；endTime的前一个月，作为环比的截止时间
            lastStartTime = DateUtil.getFirstDateOfLastMonth(startTime);
            lastEndTime = DateUtil.getFirstDateOfLastMonth(endTime);
        } else {
            //同比，上年同期（上年同一个月）开始--截止：startTime的上年同月，作为同比的开始时间；endTime的上年同月第一天，作为同比的截止时间
            lastStartTime = DateUtil.getFirstDateOfLastYear(startTime);
            lastEndTime = DateUtil.getFirstDateOfLastYear(endTime);
        }
        //------环比、同比结果，把开始结束时间置为环比、同比的开始结束
        chartResultPojoCopy.setStartTime(lastStartTime);
        chartResultPojoCopy.setEndTime(lastEndTime);
    }
    /**
     * 获取环比，同比 的开始结束时间list
     *
     * @param startTimeList 开始时间列表
     * @return com.xbongbong.pro.statistic.result.pojo.MomYoyTimeListPojo
     * @author 徐俊杰
     * @date 2019/5/14 19:43
     * @since v1.0
     */
    public static MomYoyTimeListPojo momYoyTimeListPojo(List<Integer> startTimeList) {
        MomYoyTimeListPojo momYoyTimeListPojo = new MomYoyTimeListPojo();
        //环比
        TimeListPojo momTimeListPojo = momYoyTimeListPojo.getMomTimeListPojo();
        List<Integer> moMStartTimeList = momTimeListPojo.getStartTimeList();
        List<Integer> moMEndTimeList = momTimeListPojo.getEndTimeList();
        //同比
        TimeListPojo yoyTimeListPojo = momYoyTimeListPojo.getYoyTimeListPojo();
        List<Integer> yoYStartTimeList = yoyTimeListPojo.getStartTimeList();
        List<Integer> yoYEndTimeList = yoyTimeListPojo.getEndTimeList();
        //环比，上月开始--截止
        //startTime的前一个月，作为环比的开始时间
        Integer firstStartTime = DateUtil.getFirstDateOfLastMonth(startTimeList.get(0));
        moMStartTimeList.add(firstStartTime);
        for (int i = 0; i < startTimeList.size(); i++) {
            Integer startTime = startTimeList.get(i);
            //上月的时间list，不用再计算，直接错位获取startTimeList的时间即可
            //环比上月的endTime即当月时间列表的开始
            moMEndTimeList.add(startTime);
            if (i > 0) {
                moMStartTimeList.add(startTimeList.get(i-1));
            }
            //同比，上年同期（上年同一个月）开始--截止
            //startTime的上年同月，作为同比的开始时间
            Integer lastYearStartTime = DateUtil.getFirstDateOfLastYear(startTime);
            //endTime的上年同月，作为同比的结束时间
            Integer lastYearEndTime = DateUtil.getLastDateOfLastYear(startTime);
            yoYStartTimeList.add(lastYearStartTime);
            yoYEndTimeList.add(lastYearEndTime);
        }
        return momYoyTimeListPojo;
    }
    /**
     * 格式化double型数值
     * @param chartFlag false非图，true图 图【不需要】把数字格式化为带逗号的形式
     * @param valueTypeEnum 系统指标枚举
     * @param thousandSwitchEnable 万元开关是否开启
     * @param value 要被格式化的double型数值
     * @param numFormatEnum 数值格式,若不需要就传NumFormatEnum.DEFAULT
     * @param numFormatFlag 是否已格式化数值格式
     * @return java.lang.String
     * @author zcp
     * @date 2019/5/10 16:11
     * @since v1.0
     * @version v1.0
     */
    public static String formatValue2Double(boolean chartFlag, ValueTypeEnum valueTypeEnum, boolean thousandSwitchEnable, double value, NumFormatEnum numFormatEnum, Boolean numFormatFlag){
        if (valueTypeEnum == null) {
            //double格式化，格式化为两位小数的形式，如“10000005.22”
            return StringUtil.formatDecimal(value);
        }
        return formatValueDouble(chartFlag, valueTypeEnum, thousandSwitchEnable, value, numFormatEnum, numFormatFlag);
    }

    /**
     * 格式化double型数值
     * @param chartFlag false非图，true图 图【不需要】把数字格式化为带逗号的形式
     * @param valueTypeEnum 系统指标枚举
     * @param thousandSwitchEnable 万元开关是否开启
     * @param value 要被格式化的string型数值
     * @param numFormatEnum 数值格式,若不需要就传NumFormatEnum.DEFAULT
     * @param numFormatFlag 是否已格式化数值格式
     * @return java.lang.String
     * @author zcp
     * @date 2019/5/10 16:11
     * @since v1.0
     * @version v1.0
     */
    public static String formatValue2String(boolean chartFlag, ValueTypeEnum valueTypeEnum, boolean thousandSwitchEnable, String value, NumFormatEnum numFormatEnum, Boolean numFormatFlag){
        if (StringUtil.isEmpty(value) || valueTypeEnum == null) {
            return value;
        }
        //当数字过大，变为科学计数法形式时，用isNumeric、isDigital判断肯定不为数字，而这种科学计数法形式的数字也要处理，不能直接返回
        Double valueDouble = StringUtil.toDouble(value, 0D);
        if (!StringUtil.isNumeric(value) && !StringUtil.isDigital(value)){
            if (valueDouble == null || valueDouble == 0){
                //当用isNumeric、isDigital判断不为数字，且toDouble后也没转为数字（排除了科学计数法形式），则说明就是不是数字，不需要处理格式，直接返回即可
                return value;
            }
        }
        switch (valueTypeEnum) {
            case VALUE_MONEY:
            case VALUE_DOUBLE:
                return formatValueDouble(chartFlag, valueTypeEnum, thousandSwitchEnable, valueDouble, numFormatEnum, numFormatFlag);
            default:
                //int或其它类型则直接返回（比如柱状图内各个桶内的int型值无需处理）
                return value;
        }
    }

    /**
     * 格式化金额的单位：当开启了万元开关且原单位是“元”时，则变为“万元”
     * @param thousandSwitch 万元开关，true开启、false否
     * @param unit 单位
     * @return java.lang.String
     * @author zcp
     * @date 2019/6/12 20:42
     * @since v1.0
     * @version v1.0
     */
    public static String formatUnit(boolean thousandSwitch, String unit) {
        String unitFormat = unit;
        if (thousandSwitch && MoneyUnitEnum.YUAN.getUnit().equals(unit)) {
            //万元
            unitFormat = MoneyUnitEnum.TEN_THOUSAND_YUAN.getUnit();
        }
        return unitFormat;
    }

    /**
     * 某个时间（timeLong）距离当前时间有多少天，如果timeLong超过了当前时间，则按照0计算
     * @param timeLong 时间戳（秒）
     * @return java.lang.String
     * @author zcp
     * @date 2019/6/4 14:42
     * @since v1.0
     * @version v1.0
     */
    public static String getTimeLast(Long timeLong) {
        if (timeLong == null) {
            return "-";
        } else{
            int time = timeLong.intValue();
            int now = DateUtil.getTodayInt();
            Integer day = DateUtil.lastConnect(time, now);
            if (day < 0) {
                return "0";
            } else {
                return String.valueOf(day);
            }
        }
    }

    /**
     * 处理分组和图标样式（首页资金管理）
     *
     * @param chartResultValueDetailVO 图表请求入参
     * @param systemCodeEnum 系统图表唯一标识
     * @author 徐俊杰
     * @date 2020/3/11 15:44
     * @since v1.0
     * @date 2020/4/22 by zcp 同样功能方法合并至util内，且去除循环内读取PaasMenuEntity，改为读取枚举内的icon和color ，以防影响性能
     */
    public static void dealWithGroupIconColor(ChartResultValueDetailVO chartResultValueDetailVO, SystemCodeEnum systemCodeEnum) {
        //设置分组
        chartResultValueDetailVO.setGroup(FundStatisticsConstant.CLAUSE);
        //设置图标和颜色
        dealWithIconColor(chartResultValueDetailVO, systemCodeEnum);
    }

    /**
     * 计算分桶的size
     * @param chartPkParamPojo
     * @return int
     * @author zcp
     * @since v1.0
     * @version v1.0
     */
    public static int getTermSize(ChartPkParamPojo chartPkParamPojo) {
        List<String> checkUserIdIn = chartPkParamPojo.getCheckUserIdIn();
        int size = Objects.isNull(chartPkParamPojo.getUserIdIn()) ? 0 : chartPkParamPojo.getUserIdIn().size();
        int maxSize = Math.max(size, checkUserIdIn.size());
        return maxSize + BasicConstant.FIVE;
    }

    /**
     * 格式化数值和单位
     * @param value 原值
     * @param numFormatEnum 格式化类型
     * @param unit 单位
     * @return java.lang.String
     * @author xinpeng.jiang
     * @date 2022/2/9 19:10
     * @version 1.0
     */
    public static String formatValAndUnit4Num(BigDecimal value, NumFormatEnum numFormatEnum, String unit) {
        if (value == null) {
            return "";
        }
        BigDecimal formatValue = formatVal4Num(value, numFormatEnum);
        if (unit == null) {
            return String.valueOf(formatValue);
        }
        return formatValue + unit;
    }

    /**
     * 格式化数值和单位，并加千分位符
     * @param value 原值
     * @param numFormatEnum 格式化类型
     * @param unit 单位
     * @return java.lang.String
     * @author xinpeng.jiang
     * @date 2022/2/9 19:10
     * @version 1.0
     */
    public static String formatValAndUnit2Thousands(BigDecimal value, NumFormatEnum numFormatEnum, String unit) {
        if (value == null) {
            return "";
        }
        BigDecimal formatVal = formatVal4Num(value, numFormatEnum);
        String formatValStr = StringUtil.formatDouble(formatVal);
        if (unit == null) {
            return formatValStr;
        }
        return formatValStr + unit;
    }

    /**
     * 数值格式转换，并加千分位符
     * @param value 原值
     * @param numFormatEnum 格式化类型
     * @return java.math.BigDecimal 格式化后的值
     * @author xinpeng.jiang
     * @date 2022/2/9 17:25
     * @version 1.0
     */
    public static String formatVal2Thousands(BigDecimal value, NumFormatEnum numFormatEnum) {
        BigDecimal formatVal = formatVal4Num(value, numFormatEnum);
        return StringUtil.formatDouble(formatVal);
    }

    /**
     * 数值格式转换，目前支持千、万、百万、亿，默认保留两位
     * @param value 原值
     * @param numFormatEnum 格式化类型
     * @return java.math.BigDecimal 格式化后的值
     * @author xinpeng.jiang
     * @date 2022/2/9 17:25
     * @version 1.0
     */
    public static BigDecimal formatVal4Num(BigDecimal value, NumFormatEnum numFormatEnum) {
        return formatVal4Num(value, numFormatEnum, 2);
    }

    /**
     * 数值格式转换，目前支持千、万、百万、亿
     * @param value 原值
     * @param numFormatEnum 格式化类型
     * @param scale 小数位数
     * @return java.math.BigDecimal 格式化后的值
     * @author xinpeng.jiang
     * @date 2022/2/9 17:25
     * @version 1.0
     */
    public static BigDecimal formatVal4Num(BigDecimal value, NumFormatEnum numFormatEnum, Integer scale) {
        if (value == null) {
            return value;
        }
        // 国内外习惯不同，要分开处理
        Locale locale = LocaleContextHolder.getLocale();
        if (Objects.equals(locale.getLanguage(), I18nStringConstant.ENGLISH_LANGUAGE)) {
            switch (numFormatEnum) {
                case THOUSAND:
                case TEN_THOUSAND:
                    value = value.divide(new BigDecimal(1000), scale, RoundingMode.HALF_UP);
                    break;
                case MILLION:
                case HUNDRED_MILLION:
                    value = value.divide(new BigDecimal(1000000), scale, RoundingMode.HALF_UP);
                    break;
                default:
                    value = value.setScale(scale, RoundingMode.HALF_UP);
                    break;
            }
        } else {
            switch (numFormatEnum) {
                case THOUSAND:
                    value = value.divide(new BigDecimal(1000), scale, RoundingMode.HALF_UP);
                    break;
                case TEN_THOUSAND:
                    value = value.divide(new BigDecimal(10000), scale, RoundingMode.HALF_UP);
                    break;
                case MILLION:
                    value = value.divide(new BigDecimal(1000000), scale, RoundingMode.HALF_UP);
                    break;
                case HUNDRED_MILLION:
                    value = value.divide(new BigDecimal(100000000), scale, RoundingMode.HALF_UP);
                    break;
                default:
                    value = value.setScale(scale, RoundingMode.HALF_UP);
                    break;
            }
        }
        return value;
    }

    /**
     * 数值格式转换逆向处理，会有精度问题
     * @param value 已被格式化的值（单位已去除）
     * @param numFormatEnum 格式化类型
     * @return java.math.BigDecimal 还原的值
     * @author xinpeng.jiang
     * @date 2022/2/9 17:25
     * @version 1.0
     */
    public static BigDecimal formatVal4NumRevert(BigDecimal value, NumFormatEnum numFormatEnum) {
        if (value == null) {
            return value;
        }
        // 国内外习惯不同，要分开处理
        Locale locale = LocaleContextHolder.getLocale();
        if (Objects.equals(locale.getLanguage(), I18nStringConstant.ENGLISH_LANGUAGE)) {
            switch (numFormatEnum) {
                case THOUSAND:
                case TEN_THOUSAND:
                    value = value.multiply(new BigDecimal(1000));
                    break;
                case MILLION:
                case HUNDRED_MILLION:
                    value = value.multiply(new BigDecimal(1000000));
                    break;
                default:
                    break;
            }
        } else {
            switch (numFormatEnum) {
                case THOUSAND:
                    value = value.multiply(new BigDecimal(1000));
                    break;
                case TEN_THOUSAND:
                    value = value.multiply(new BigDecimal(10000));
                    break;
                case MILLION:
                    value = value.multiply(new BigDecimal(1000000));
                    break;
                case HUNDRED_MILLION:
                    value = value.multiply(new BigDecimal(100000000));
                    break;
                default:
                    break;
            }
        }
        return value;
    }

    //-------------------private方法-------------------

    /**
     * 格式化double型数值
     * @param chartFlag false非图，true图 图【不需要】把数字格式化为带逗号的形式
     * @param valueTypeEnum 系统指标枚举
     * @param thousandSwitchEnable 万元开关是否开启
     * @param value 要被格式化的double型数值
     * @param numFormatEnum 数值格式,若不需要就传NumFormatEnum.DEFAULT.getCode()
     * @param numFormatFlag 是否已格式化数值格式
     * @return java.lang.String
     * @author zcp
     * @date 2019/6/12 19:34
     * @since v1.0
     * @version v1.0
     */
    private static String formatValueDouble(boolean chartFlag, ValueTypeEnum valueTypeEnum, boolean thousandSwitchEnable, double value, NumFormatEnum numFormatEnum, Boolean numFormatFlag) {
        switch (valueTypeEnum) {
            case VALUE_MONEY:
                /**
                 金额格式化，格式化为三位一个逗号的形式，如“100,000,05.22”
                 金额可能还需要考虑万元开关
                 */
                if (chartFlag) {
                    // 处理数值格式
                    if (BooleanUtils.isNotTrue(numFormatFlag)) {
                        // 处理数值格式，为了兼容老版本万元，放在其之后
                        return String.valueOf(formatVal4Num(BigDecimal.valueOf(value), numFormatEnum));
                    }
                    //double格式化，格式化为两位小数的形式，如“10000005.22”
                    return StringUtil.formatDecimal(value);
                } else {
                    // 仅处理万元，优先级高
                    if (thousandSwitchEnable) {
                        value = Arith.div(value, 10000);
                        return StringUtil.formatDouble(value);
                    }
                    // 处理数值格式，为了兼容老版本万元，放在其之后
                    if (BooleanUtils.isNotTrue(numFormatFlag)) {
                        return String.valueOf(formatVal4Num(BigDecimal.valueOf(value), numFormatEnum));
                    }
                    return StringUtil.formatDouble(value);
                }
            case VALUE_DOUBLE:
                if (chartFlag) {
                    //double格式化，格式化为两位小数的形式，如“10000005.22”
                    return StringUtil.formatDecimal(value);
                } else {
                    //double型格式化，格式化为三位一个逗号的形式，如“100,000,05.22”
                    return StringUtil.formatDouble(value);
                }
            default:
                //double格式化，格式化为两位小数的形式，如“10000005.22”
                return StringUtil.formatDecimal(value);
        }
    }

    /**
     * 处理图标样式（首页资金管理）
     *
     * @param chartResultValueDetailVO 图表请求入参
     * @param systemCodeEnum 系统图表唯一标识
     * @author 徐俊杰
     * @date 2020/3/11 15:45
     * @since v1.0
     * @date 2020/4/22 by zcp 同样功能方法合并至util内，且去除循环内读取PaasMenuEntity，改为读取枚举内的icon和color ，以防影响性能
     */
    private static void dealWithIconColor(ChartResultValueDetailVO chartResultValueDetailVO, SystemCodeEnum systemCodeEnum) {
        IndicatorRuleEnum indicatorRuleEnum = systemCodeEnum.getIndicatorRuleEnum();
        AccessLinkEnum accessLinkEnum = indicatorRuleEnum.getAccessLinkEnum();
        if (accessLinkEnum == null) {
            return;
        }
        if (StringUtil.isEmpty(chartResultValueDetailVO.getIcon())) {
            chartResultValueDetailVO.setIcon(accessLinkEnum.getIcon());
        }
        if (StringUtil.isEmpty(chartResultValueDetailVO.getColor())) {
            chartResultValueDetailVO.setColor(accessLinkEnum.getColor());
        }
    }
}
